#pragma once

#include "doc/convert/attribute_convert/multivalue_attribute_convertor.h"

namespace hawking {
namespace indexlib {

/*
    memory layout:
    | ArrayLengthType(string count) | StringLengthType(string1 length) | string1 | | StringLengthType(string2 length) | string2 | ......
*/
class MultiStringAttributeConvertor : public MultiValueAttributeConvertor<char> {
public:
    MultiStringAttributeConvertor(util::ColumnType column_type) :
        MultiValueAttributeConvertor<char>(column_type) {}
    ~MultiStringAttributeConvertor() = default;

protected:
    // str_count + every `string_length + string`
    std::string_view InnerEncode_(const util::FieldValue* field_value, Pool* pool) override {
        size_t buf_size =
            sizeof(ArrayLengthType) +
            field_value->bytes_values().values_size() * sizeof(StringLengthType);
        for (int32_t idx = 0; idx < field_value->bytes_values().values_size(); ++idx) {
            buf_size += field_value->bytes_values().values(idx).length();
        }

        char* begin = Allocate_(pool, buf_size);
        char* buffer = begin;
        ArrayLengthType str_count =
            static_cast<ArrayLengthType>(field_value->bytes_values().values_size());
        AppendCount_(str_count, buffer);
        AppendOffsetAndData_(field_value->bytes_values(), std::ref(buffer));
        return std::string_view(begin, buffer - begin);
    }

private:
    void AppendOffsetAndData_(const util::BytesList& bytes_list, char*& buffer) const {
        for (int32_t idx = 0; idx < bytes_list.values_size(); ++idx) {
            const std::string& cur_str = bytes_list.values(idx);
            // write string length
            StringLengthType str_length = cur_str.length();
            std::memcpy(buffer, &str_length, sizeof(str_length));
            buffer += sizeof(str_length);

            // write string
            std::memcpy(buffer, cur_str.data(), cur_str.length());
            buffer += cur_str.length();
        }
    }
};

}
}